﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Community.StaticAnalysis.Reliability.Rules;
using Microsoft.FxCop.Sdk;
using Community.StaticAnalysis.Rules.Tests.Dummies;
using System.Globalization;

namespace Community.StaticAnalysis.Rules.Tests.Integration
{
    /// <summary>
    /// The testfixture is an integration test for the DisposeObjectBeforeOutOfScopeRule.
    /// It checks if the number of problems are correct. 
    /// </summary>
    [TestClass]
    public class DisposeObjectBeforeOutOfScopeRuleTestFixture
    {
        #region Constants

        private const string WRONG_PROBlEM_COUNT_MESSAGE = "There can only be one problem in the Problems property";
        private const string WRONG_RESOLUTION_NAME_MESSAGE = "The resolution name of the problem must be '{0}'";

        #endregion

        #region Tests

        [TestMethod]
        public void VerifyProblemsOnlyContainVariableResolution()
        {
            const int EXPECT_PROBLEM_COUNT = 1;

            DisposeObjectBeforeOutOfScopeRule rule = new DisposeObjectBeforeOutOfScopeRule();

            string methodName = ND2000SampleClass.MethodNameContainsLocalThatIsNotDisposed;
            Method method = CcUtil.GetMethod(typeof(ND2000SampleClass), methodName);

            ProblemCollection problems = rule.Check(method);

            Assert.AreEqual(EXPECT_PROBLEM_COUNT, problems.Count, WRONG_PROBlEM_COUNT_MESSAGE);

            Problem problem = problems[0];

            Assert.AreEqual(DisposeObjectBeforeOutOfScopeRule.VARIABLE_RESOLUTION_NAME,
                problem.Resolution.Name,
                true,
                CultureInfo.InvariantCulture,
                WRONG_RESOLUTION_NAME_MESSAGE,
                DisposeObjectBeforeOutOfScopeRule.VARIABLE_RESOLUTION_NAME);
        }


        [TestMethod]
        public void VerifyProblemsOnlyContainsMethodResolution() {
            const int EXPECT_PROBLEM_COUNT = 1;
            DisposeObjectBeforeOutOfScopeRule rule = new DisposeObjectBeforeOutOfScopeRule();

            string methodName = ND2000SampleClass.MethodNameCallsAMethodThatReturnsAObjectAndForgotToCallDispose;
            Method method = CcUtil.GetMethod(typeof(ND2000SampleClass), methodName);

            ProblemCollection problems = rule.Check(method);

            Assert.AreEqual(EXPECT_PROBLEM_COUNT, problems.Count, WRONG_PROBlEM_COUNT_MESSAGE);

            Problem problem = problems[0];

            Assert.AreEqual(DisposeObjectBeforeOutOfScopeRule.METHOD_CALL_RESOLUTION_NAME,
                problem.Resolution.Name,
                true,
                CultureInfo.InvariantCulture,
                WRONG_RESOLUTION_NAME_MESSAGE,
                DisposeObjectBeforeOutOfScopeRule.METHOD_CALL_RESOLUTION_NAME);
        }


        [TestMethod]
        public void VerifyProblemsOnlyContainsConstructResolution()
        {
            const int EXPECT_PROBLEM_COUNT = 1;
            DisposeObjectBeforeOutOfScopeRule rule = new DisposeObjectBeforeOutOfScopeRule();

            string methodName = ND2000SampleClass.MethodNameCallConstructorWithoutStoringIt;
            Method method = CcUtil.GetMethod(typeof(ND2000SampleClass), methodName);

            ProblemCollection problems = rule.Check(method);

            Assert.AreEqual(EXPECT_PROBLEM_COUNT, problems.Count, WRONG_PROBlEM_COUNT_MESSAGE);

            Problem problem = problems[0];

            Assert.AreEqual(DisposeObjectBeforeOutOfScopeRule.CONSTRUCT_RESOLUTION_NAME,
                problem.Resolution.Name,
                true,
                CultureInfo.InvariantCulture,
                WRONG_RESOLUTION_NAME_MESSAGE,
                DisposeObjectBeforeOutOfScopeRule.CONSTRUCT_RESOLUTION_NAME);
        }


        #endregion
    }
}
